home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Educational / RasMol / Source / transfor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-21  |  56.1 KB  |  2,372 lines

  1. /* transfor.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, August 1995
  4.  * Version 2.6
  5.  */
  6. #include "rasmol.h"
  7.  
  8. #ifdef IBMPC
  9. #include <windows.h>
  10. #endif
  11. #ifdef APPLEMAC
  12. #include <Types.h>
  13. #include <Errors.h>
  14. #ifdef __CONDITIONALMACROS__
  15. #include <Printing.h>
  16. #else
  17. #include <PrintTraps.h>
  18. #endif
  19. #endif
  20. #include <stdio.h>
  21. #include <math.h>
  22.  
  23. #define TRANSFORM
  24. #include "molecule.h"
  25. #include "abstree.h"
  26. #include "transfor.h"
  27. #include "command.h"
  28. #include "render.h"
  29. #include "repres.h"
  30. #include "graphics.h"
  31.  
  32.  
  33. typedef struct {
  34.         short col;
  35.         short shade;
  36.         unsigned char r;
  37.         unsigned char g;
  38.         unsigned char b;
  39.           } ShadeRef;
  40.  
  41.  
  42. #define CPKMAX  16
  43. static ShadeRef CPKShade[] = {
  44.      { 0, 0, 200, 200, 200 },       /*  0 Light Grey   */
  45.      { 0, 0, 143, 143, 255 },       /*  1 Sky Blue     */
  46.      { 0, 0, 240,   0,   0 },       /*  2 Red          */
  47.      { 0, 0, 255, 200,  50 },       /*  3 Yellow       */
  48.      { 0, 0, 255, 255, 255 },       /*  4 White        */
  49.      { 0, 0, 255, 192, 203 },       /*  5 Pink         */
  50.      { 0, 0, 218, 165,  32 },       /*  6 Golden Rod   */
  51.      { 0, 0,   0,   0, 255 },       /*  7 Blue         */
  52.      { 0, 0, 255, 165,   0 },       /*  8 Orange       */
  53.      { 0, 0, 128, 128, 144 },       /*  9 Dark Grey    */
  54.      { 0, 0, 165,  42,  42 },       /* 10 Brown        */
  55.      { 0, 0, 160,  32, 240 },       /* 11 Purple       */
  56.      { 0, 0, 255,  20, 147 },       /* 12 Deep Pink    */
  57.      { 0, 0,   0, 255,   0 },       /* 13 Green        */
  58.      { 0, 0, 178,  34,  34 },       /* 14 Fire Brick   */
  59.      { 0, 0,  34, 139,  34 } };     /* 15 Forest Green */
  60.  
  61.  
  62. static ShadeRef Shapely[] = {
  63.      { 0, 0, 140, 255, 140 },    /* ALA */
  64.      { 0, 0, 255, 255, 255 },    /* GLY */
  65.      { 0, 0,  69,  94,  69 },    /* LEU */
  66.      { 0, 0, 255, 112,  66 },    /* SER */
  67.      { 0, 0, 255, 140, 255 },    /* VAL */
  68.      { 0, 0, 184,  76,   0 },    /* THR */
  69.      { 0, 0,  71,  71, 184 },    /* LYS */
  70.      { 0, 0, 160,   0,  66 },    /* ASP */
  71.      { 0, 0,   0,  76,   0 },    /* ILE */
  72.      { 0, 0, 255, 124, 112 },    /* ASN */
  73.      { 0, 0, 102,   0,   0 },    /* GLU */
  74.      { 0, 0,  82,  82,  82 },    /* PRO */
  75.      { 0, 0,   0,   0, 124 },    /* ARG */
  76.      { 0, 0,  83,  76,  66 },    /* PHE */
  77.      { 0, 0, 255,  76,  76 },    /* GLN */
  78.      { 0, 0, 140, 112,  76 },    /* TYR */
  79.      { 0, 0, 112, 112, 255 },    /* HIS */
  80.      { 0, 0, 255, 255, 112 },    /* CYS */
  81.      { 0, 0, 184, 160,  66 },    /* MET */
  82.      { 0, 0,  79,  70,   0 },    /* TRP */
  83.  
  84.      { 0, 0, 255,   0, 255 },    /* ASX */
  85.      { 0, 0, 255,   0, 255 },    /* GLX */
  86.      { 0, 0, 255,   0, 255 },    /* PCA */
  87.      { 0, 0, 255,   0, 255 },    /* HYP */
  88.  
  89.      { 0, 0, 160, 160, 255 },    /*   A */
  90.      { 0, 0, 255, 140,  75 },    /*   C */
  91.      { 0, 0, 255, 112, 112 },    /*   G */
  92.      { 0, 0, 160, 255, 160 },    /*   T */
  93.  
  94.      { 0, 0, 184, 184, 184 },    /* 28 -> BackBone */
  95.      { 0, 0,  94,   0,  94 },    /* 29 -> Special  */
  96.      { 0, 0, 255,   0, 255 } };  /* 30 -> Default  */
  97.  
  98.      
  99. static ShadeRef AminoShade[] = {
  100.      { 0, 0, 230,  10,  10 },    /*  0  ASP, GLU      */
  101.      { 0, 0,  20,  90, 255 },    /*  1  LYS, ARG      */
  102.      { 0, 0, 130, 130, 210 },    /*  2  HIS           */
  103.      { 0, 0, 250, 150,   0 },    /*  3  SER, THR      */
  104.      { 0, 0,   0, 220, 220 },    /*  4  ASN, GLN      */
  105.      { 0, 0, 230, 230,   0 },    /*  5  CYS, MET      */
  106.      { 0, 0, 200, 200, 200 },    /*  6  ALA           */
  107.      { 0, 0, 235, 235, 235 },    /*  7  GLY           */
  108.      { 0, 0,  15, 130,  15 },    /*  8  LEU, VAL, ILE */
  109.      { 0, 0,  50,  50, 170 },    /*  9  PHE, TYR      */
  110.      { 0, 0, 180,  90, 180 },    /* 10  TRP           */
  111.      { 0, 0, 220, 150, 130 },    /* 11  PRO, PCA, HYP */
  112.      { 0, 0, 190, 160, 110 } };  /* 12  Others        */
  113.  
  114. static int AminoIndex[] = {
  115.       6, /*ALA*/   7, /*GLY*/   8, /*LEU*/   3,  /*SER*/
  116.       8, /*VAL*/   3, /*THR*/   1, /*LYS*/   0,  /*ASP*/
  117.       8, /*ILE*/   4, /*ASN*/   0, /*GLU*/  11,  /*PRO*/
  118.       1, /*ARG*/   9, /*PHE*/   4, /*GLN*/   9,  /*TYR*/
  119.       2, /*HIS*/   5, /*CYS*/   5, /*MET*/  10,  /*TRP*/
  120.       4, /*ASX*/   4, /*GLX*/  11, /*PCA*/  11   /*HYP*/
  121.               };
  122.  
  123. static ShadeRef HBondShade[] = {
  124.      { 0, 0, 255, 255, 255 },    /* 0  Offset =  2   */
  125.      { 0, 0, 255,   0, 255 },    /* 1  Offset =  3   */
  126.      { 0, 0, 255,   0,   0 },    /* 2  Offset =  4   */
  127.      { 0, 0, 255, 165,   0 },    /* 3  Offset =  5   */
  128.      { 0, 0,   0, 255, 255 },    /* 4  Offset = -3   */
  129.      { 0, 0,   0, 255,   0 },    /* 5  Offset = -4   */
  130.      { 0, 0, 255, 255,   0 } };  /* 6  Others        */
  131.  
  132.  
  133. static ShadeRef StructShade[] = {
  134.      { 0, 0, 255, 255, 255 },    /* 0  Default     */
  135.      { 0, 0, 255,   0, 128 },    /* 1  Alpha Helix */
  136.      { 0, 0, 255, 200,   0 },    /* 2  Beta Sheet  */
  137.      { 0, 0,  96, 128, 255 } };  /* 3  Turn        */
  138.  
  139. static ShadeRef PotentialShade[] = {
  140.      { 0, 0, 255,   0,   0 },    /* 0  Red     25 < V       */
  141.      { 0, 0, 255, 165,   0 },    /* 1  Orange  10 < V <  25 */
  142.      { 0, 0, 255, 255,   0 },    /* 2  Yellow   3 < V <  10 */
  143.      { 0, 0,   0, 255,   0 },    /* 3  Green    0 < V <   3 */
  144.      { 0, 0,   0, 255, 255 },    /* 4  Cyan    -3 < V <   0 */
  145.      { 0, 0,   0,   0, 255 },    /* 5  Blue   -10 < V <  -3 */
  146.      { 0, 0, 160,  32, 240 },    /* 6  Purple -25 < V < -10 */
  147.      { 0, 0, 255, 255, 255 } };  /* 7  White        V < -25 */
  148.  
  149.  
  150. /* Macros for commonly used loops */
  151. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  152.              for(group=chain->glist;group;group=group->gnext)    \
  153.              for(ptr=group->alist;ptr;ptr=ptr->anext)
  154. #define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext) 
  155. #define ForEachBack  for(chain=Database->clist;chain;chain=chain->cnext) \
  156.              for(bptr=chain->blist;bptr;bptr=bptr->bnext)
  157.  
  158. #define MatchChar(a,b)   (((a)=='#')||((a)==(b)))
  159. #define RootSix          2.44948974278
  160.  
  161.  
  162. static ShadeRef ScaleRef[MAXSHADE];
  163. static int MaskColour[MAXMASK];
  164. static int MaskShade[MAXMASK];
  165. static int ScaleCount;
  166. static int LastShade;
  167.  
  168. static Real LastRX,LastRY,LastRZ;
  169. static Real Zoom;
  170.  
  171.  
  172.  
  173. void DetermineClipping()
  174. {
  175.     register int temp;
  176.     register int max;
  177.  
  178.     max = 0;
  179.     if( DrawAtoms && (MaxAtomRadius>max) )  max = MaxAtomRadius;
  180.     if( DrawBonds && (MaxBondRadius>max) )  max = MaxBondRadius;
  181.        
  182.     temp = ImageRadius + max;
  183.     if( (YOffset>=temp) && (XOffset>=temp) && (YOffset+temp<YRange) )
  184.     {   if( UseStereo )
  185.         {   UseScreenClip = (XOffset+temp) >= (XRange>>1);
  186.         } else UseScreenClip = (XOffset+temp) >= XRange;
  187.     } else UseScreenClip = True;
  188. }
  189.  
  190.  
  191.  
  192. void SetRadiusValue( rad )
  193.     int rad;
  194. {
  195.     register int irad,change;
  196.     register Chain __far *chain;
  197.     register Group __far *group;
  198.     register Atom __far *ptr;
  199.  
  200.     if( !Database )
  201.     return;
  202.  
  203.     irad = (int)(Scale*rad);
  204.     MaxAtomRadius = 0;
  205.     DrawAtoms = False;
  206.     change = False;
  207.  
  208.     ForEachAtom
  209.     if( ptr->flag & SelectFlag )
  210.     {   if( irad>MaxAtomRadius )
  211.         MaxAtomRadius = irad;
  212.         ptr->flag |= SphereFlag;
  213.         ptr->radius = rad;
  214.         ptr->irad = irad;
  215.         change = True;
  216.     } else if( ptr->flag & SphereFlag )
  217.     {   DrawAtoms = True;
  218.         if( ptr->irad>MaxAtomRadius )
  219.         MaxAtomRadius = ptr->irad;
  220.     }
  221.  
  222.     if( change )
  223.     {   DrawAtoms = True;
  224.     DetermineClipping();
  225.     VoxelsClean = False;
  226.     BucketFlag = False;
  227.     }
  228. }
  229.  
  230. void SetRadiusTemperature()
  231. {
  232.     register int rad,irad,change;
  233.     register Chain __far *chain;
  234.     register Group __far *group;
  235.     register Atom __far *ptr;
  236.  
  237.     if( !Database )
  238.     return;
  239.  
  240.     MaxAtomRadius = 0;
  241.     DrawAtoms = False;
  242.     change = False;
  243.  
  244.     ForEachAtom
  245.     if( (ptr->flag&SelectFlag) && (ptr->temp>0) )
  246.     {   rad = (5*ptr->temp)>>1;
  247.         if( rad>500 ) rad = 500;
  248.  
  249.         irad = (int)(Scale*rad);
  250.         if( irad>MaxAtomRadius )
  251.         MaxAtomRadius = irad;
  252.         ptr->flag |= SphereFlag;
  253.         ptr->radius = rad;
  254.         ptr->irad = irad;
  255.         change = True;
  256.     } else if( ptr->flag & SphereFlag )
  257.     {   DrawAtoms = True;
  258.         if( ptr->irad>MaxAtomRadius )
  259.         MaxAtomRadius = ptr->irad;
  260.     }
  261.  
  262.     if( change )
  263.     {   DrawAtoms = True;
  264.     DetermineClipping();
  265.     VoxelsClean = False;
  266.     BucketFlag = False;
  267.     }
  268. }
  269.  
  270.  
  271. void SetVanWaalRadius()
  272. {
  273.     register int rad,change;
  274.     register Chain __far *chain;
  275.     register Group __far *group;
  276.     register Atom __far *ptr;
  277.  
  278.     if( !Database )
  279.     return;
  280.  
  281.     MaxAtomRadius = 0;
  282.     DrawAtoms = False;
  283.     change = False;
  284.  
  285.     ForEachAtom
  286.     if( ptr->flag&SelectFlag )
  287.     {   rad = ElemVDWRadius(ptr->elemno);
  288.         ptr->irad = (int)(Scale*rad);
  289.         ptr->radius = rad;
  290.         change = True;
  291.  
  292.         ptr->flag |=SphereFlag;
  293.         if( ptr->irad>MaxAtomRadius )
  294.         MaxAtomRadius = ptr->irad;
  295.     } else if( ptr->flag&SphereFlag )
  296.     {   DrawAtoms = True;
  297.         if( ptr->irad>MaxAtomRadius )
  298.         MaxAtomRadius = ptr->irad;
  299.     }
  300.  
  301.     if( change )
  302.     {   DrawAtoms = True;
  303.     DetermineClipping();
  304.     VoxelsClean = False;
  305.     BucketFlag = False;
  306.     }
  307. }
  308.  
  309.  
  310. void DisableSpacefill()
  311. {
  312.     register Chain __far *chain;
  313.     register Group __far *group;
  314.     register Atom __far *ptr;
  315.  
  316.     if( !Database || !DrawAtoms )
  317.     return;
  318.  
  319.     MaxAtomRadius = 0;
  320.     DrawAtoms = False;
  321.     
  322.     ForEachAtom
  323.     if( !(ptr->flag&SelectFlag) )
  324.     {   if( ptr->flag&SphereFlag )
  325.         {   if( ptr->irad>MaxAtomRadius )
  326.             MaxAtomRadius = ptr->irad;
  327.         DrawAtoms = True;
  328.         }
  329.     } else if( ptr->flag&SphereFlag )
  330.         ptr->flag &= ~SphereFlag;
  331.  
  332.     DetermineClipping();
  333.     VoxelsClean = False;
  334.     BucketFlag = False;
  335. }
  336.  
  337.  
  338.  
  339. void EnableWireframe( mask, rad )
  340.     int mask, rad;
  341. {
  342.     register Bond __far *bptr;
  343.     register int flag, irad;
  344.  
  345.     if( !Database )
  346.     return;
  347.  
  348.     DrawBonds = False;
  349.     MaxBondRadius = 0;
  350.     irad = (int)(Scale*rad);
  351.  
  352.     ForEachBond
  353.     {   flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag
  354.                : bptr->dstatom->flag | bptr->srcatom->flag;
  355.  
  356.     if( flag&SelectFlag )
  357.     {   DrawBonds = True;
  358.         bptr->flag &= ~DrawBondFlag;
  359.             bptr->flag |= mask;
  360.         if( mask == CylinderFlag )
  361.         {   if( irad>MaxBondRadius )
  362.             MaxBondRadius = irad;
  363.         bptr->radius = rad;
  364.         bptr->irad = irad;
  365.         }
  366.     } else if( bptr->flag&DrawBondFlag )
  367.     {    DrawBonds = True;
  368.          if( bptr->flag&CylinderFlag )
  369.          if( bptr->irad>MaxBondRadius )
  370.              MaxBondRadius = bptr->irad;
  371.     }
  372.     }
  373.     DetermineClipping();
  374. }
  375.  
  376.  
  377. void DisableWireframe()
  378. {
  379.     register Bond __far *bptr;
  380.     register int flag;
  381.  
  382.     if( !Database || !DrawBonds )
  383.     return;
  384.  
  385.     DrawBonds = False;
  386.     MaxBondRadius = 0;
  387.  
  388.     ForEachBond
  389.     {   flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag
  390.                : bptr->dstatom->flag | bptr->srcatom->flag;
  391.  
  392.     if( flag&SelectFlag )
  393.     {   bptr->flag &= ~DrawBondFlag;
  394.     } else if( bptr->flag&DrawBondFlag )
  395.     {   DrawBonds = True;
  396.         if( bptr->flag&CylinderFlag )
  397.         if( bptr->irad>MaxBondRadius )
  398.             MaxBondRadius = bptr->irad;
  399.     }
  400.     }
  401.     DetermineClipping();
  402. }
  403.  
  404.  
  405. void EnableBackbone( mask, rad )
  406.     int mask, rad;
  407. {
  408.     register Chain __far *chain;
  409.     register Bond __far *bptr;
  410.     register int flag,irad;
  411.  
  412.     if( !Database )
  413.     return;
  414.  
  415.     irad = (int)(Scale*rad);
  416.  
  417.     ForEachBack
  418.     {   flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag
  419.                : bptr->dstatom->flag | bptr->srcatom->flag;
  420.  
  421.     if( flag&SelectFlag )
  422.     {   bptr->flag &= ~DrawBondFlag;
  423.             bptr->flag |= mask;
  424.         if( mask == CylinderFlag )
  425.             {   bptr->radius = rad;
  426.         bptr->irad = irad;
  427.         }
  428.     } 
  429.     }
  430. }
  431.  
  432.  
  433. void DisableBackbone()
  434. {
  435.     register Chain __far *chain;
  436.     register Bond __far *bptr;
  437.  
  438.     if( !Database )
  439.     return;
  440.  
  441.     if( ZoneBoth )
  442.     {   ForEachBack
  443.         if( (bptr->dstatom->flag&bptr->srcatom->flag) & SelectFlag )
  444.         bptr->flag &= ~DrawBondFlag;
  445.     } else ForEachBack
  446.     if( (bptr->dstatom->flag|bptr->srcatom->flag) & SelectFlag )
  447.         bptr->flag &= ~DrawBondFlag;
  448. }
  449.  
  450.  
  451. void SetHBondStatus( hbonds, enable, rad )
  452.     int hbonds, enable, rad;
  453. {
  454.     register HBond __far *list;
  455.     register HBond __far *ptr;
  456.     register Atom __far *src;
  457.     register Atom __far *dst;
  458.     register int flag, irad;
  459.  
  460.     if( !Database )
  461.     return;
  462.  
  463.     if( hbonds )
  464.     {   if( enable && (InfoHBondCount<0) )
  465.         CalcHydrogenBonds();
  466.     list = Database->hlist;
  467.     } else 
  468.     {   if( enable && (InfoSSBondCount<0) )
  469.         FindDisulphideBridges();
  470.     list = Database->slist;
  471.     }
  472.  
  473.     irad = (int)(Scale*rad);
  474.     for( ptr=list; ptr; ptr=ptr->hnext )
  475.     {   src = ptr->src;  dst = ptr->dst;
  476.  
  477.     flag = ZoneBoth? src->flag&dst->flag : src->flag|dst->flag;
  478.     if( flag & SelectFlag ) 
  479.     {   ptr->flag &= ~DrawBondFlag;
  480.         if( enable )
  481.         {   if( rad )
  482.         {   ptr->flag |= CylinderFlag;
  483.             ptr->radius = rad;
  484.             ptr->irad = irad;
  485.         } else ptr->flag |= WireFlag;
  486.         }
  487.     }
  488.     }
  489. }
  490.  
  491.  
  492. void SetRibbonStatus( enable, flag, width )
  493.     int enable, flag, width;
  494. {
  495.     register Chain __far *chain;
  496.     register Group __far *group;
  497.     register Atom __far *ptr;
  498.  
  499.     if( !Database )
  500.     return;
  501.  
  502.     /* Ribbons already disabled! */
  503.     if( !enable && !DrawRibbon )
  504.     return;
  505.  
  506.     if( InfoHelixCount<0 )
  507.     DetermineStructure(False);
  508.  
  509.     DrawRibbon = False;
  510.     for( chain=Database->clist; chain; chain=chain->cnext )
  511.     for( group=chain->glist; group; group=group->gnext )
  512.         if( enable )
  513.         {   if( group->flag & DrawKnotFlag )
  514.             DrawRibbon = True;
  515.         
  516.         for( ptr=group->alist; ptr; ptr=ptr->anext )
  517.             if( IsAlphaCarbon(ptr->refno) )
  518.             {   if( ptr->flag&SelectFlag )
  519.             {   group->flag &= ~DrawKnotFlag;
  520.                 group->flag |= flag;
  521.                 if( !width )
  522.                 {   if( group->struc & (HelixFlag|SheetFlag) )
  523.                 {      group->width = 380;
  524.                 } else group->width = 100;
  525.                 } else group->width = width;
  526.                 DrawRibbon = True;
  527.             }
  528.             break;
  529.  
  530.             } else if( IsSugarPhosphate(ptr->refno) )
  531.             {   if( ptr->flag&SelectFlag )
  532.             {   group->width = width? width : 720;
  533.                 group->flag &= ~DrawKnotFlag;
  534.                 group->flag |= flag;
  535.                 DrawRibbon = True;
  536.             }
  537.             break;
  538.             }
  539.  
  540.  
  541.         } else  /* Disable Ribbon */
  542.         if( group->flag & DrawKnotFlag )
  543.         {   for( ptr=group->alist; ptr; ptr=ptr->anext )
  544.             if( IsAlphaCarbon(ptr->refno) ||
  545.                 IsSugarPhosphate(ptr->refno) )
  546.             {   if( ptr->flag&SelectFlag )
  547.                 group->flag &= ~DrawKnotFlag;
  548.                 break;
  549.             }
  550.             if( group->flag & DrawKnotFlag ) 
  551.             DrawRibbon = True;
  552.         }
  553. }
  554.  
  555.  
  556. void SetRibbonCartoons()
  557. {
  558.     register Chain __far *chain;
  559.     register Group __far *group;
  560.     register Atom __far *ptr;
  561.  
  562.     if( !Database )
  563.     return;
  564.  
  565.     if( InfoHelixCount<0 )
  566.     DetermineStructure(False);
  567.  
  568.     /* DrawBetaArrows = True; */
  569.     /* CartoonHeight = 120;   */
  570.  
  571.     DrawRibbon = False;
  572.     for( chain=Database->clist; chain; chain=chain->cnext )
  573.         for( group=chain->glist; group; group=group->gnext )
  574.         {   if( group->flag & DrawKnotFlag )
  575.                 DrawRibbon = True;
  576.                 
  577.             for( ptr=group->alist; ptr; ptr=ptr->anext )
  578.                 if( IsAlphaCarbon(ptr->refno) )
  579.                 {   if( ptr->flag&SelectFlag )
  580.                     {   group->flag &= ~DrawKnotFlag;
  581.                         if( group->struc & (HelixFlag|SheetFlag) )
  582.                         {   group->flag |= CartoonFlag;
  583.                             group->width = 380;
  584.                         } else 
  585.                         {   group->flag |= TraceFlag;
  586.                             group->width = 100;
  587.                         }
  588.                         DrawRibbon = True;
  589.                     }
  590.                     break;
  591.  
  592.                 } else if( IsSugarPhosphate(ptr->refno) )
  593.                 {   if( ptr->flag&SelectFlag )
  594.                     {   group->flag &= ~DrawKnotFlag;
  595.                         group->flag |= RibbonFlag;
  596.                         group->width = 720;
  597.                         DrawRibbon = True;
  598.                     }
  599.                     break;
  600.                 }
  601.             }
  602. }
  603.  
  604.  
  605. /*===========================*/
  606. /* Atom Selection Functions! */
  607. /*===========================*/
  608.  
  609. static void DisplaySelectCount()
  610. {
  611.     char buffer[40];
  612.  
  613.     if( FileDepth == -1 )
  614.     {   if( CommandActive )
  615.            WriteChar('\n');
  616.         CommandActive=False;
  617.  
  618.         if( SelectCount==0 )
  619.         {   WriteString("No atoms selected!\n");
  620.         } else if( SelectCount>1 )
  621.         {   sprintf(buffer,"%ld atoms selected!\n",(long)SelectCount);
  622.             WriteString(buffer);
  623.         } else WriteString("1 atom selected!\n");
  624.     }
  625.  
  626.     if( DisplayMode )
  627.         ReDrawFlag |= RFRefresh;
  628.     AdviseUpdate(AdvSelectCount);
  629. }
  630.  
  631.  
  632. void SelectZone( mask )
  633.     int mask;
  634. {
  635.     register Bond __far *bptr;
  636.     register Chain __far *chain;
  637.     register Group __far *group;
  638.     register Atom __far *ptr;
  639.  
  640.     if( !Database )
  641.         return;
  642.  
  643.     SelectCount = 0;
  644.     ForEachAtom
  645.         if( ptr->flag & mask )
  646.     {   ptr->flag |= SelectFlag;
  647.         SelectCount++;
  648.     } else ptr->flag &= ~SelectFlag;
  649.     DisplaySelectCount();
  650.  
  651.     if( ZoneBoth )
  652.     {   ForEachBond
  653.        if( (bptr->srcatom->flag&bptr->dstatom->flag) & SelectFlag )
  654.        {   bptr->flag |= SelectFlag;
  655.        } else bptr->flag &= ~SelectFlag;
  656.     } else
  657.     ForEachBond
  658.        if( (bptr->srcatom->flag|bptr->dstatom->flag) & SelectFlag )
  659.        {   bptr->flag |= SelectFlag;
  660.        } else bptr->flag &= ~SelectFlag;
  661.  
  662. }
  663.  
  664.  
  665. void RestrictZone( mask )
  666.     int mask;
  667. {
  668.     register Bond __far *bptr;
  669.     register Chain __far *chain;
  670.     register Group __far *group;
  671.     register Atom __far *ptr;
  672.     register int flag;
  673.  
  674.     if( !Database )
  675.     return;
  676.  
  677.     DrawAtoms = False;   MaxAtomRadius = 0;
  678.     DrawBonds = False;   MaxBondRadius = 0;
  679.     DrawLabels = False;
  680.     
  681.     SelectCount = 0;
  682.     ForEachAtom
  683.     if( ptr->flag & mask )
  684.     {   ptr->flag |= SelectFlag;
  685.         SelectCount++;
  686.  
  687.         if( ptr->flag & SphereFlag )
  688.         {   DrawAtoms = True;
  689.         if( ptr->irad>MaxAtomRadius )
  690.             MaxAtomRadius = ptr->irad;
  691.         }
  692.  
  693.             if( ptr->label )
  694.                 DrawLabels = True;
  695.     } else 
  696.         {   ptr->flag &= ~(SelectFlag|SphereFlag);
  697.             if( ptr->label )
  698.             {   DeleteLabel( (Label*)ptr->label );
  699.                 ptr->label = (void*)0;
  700.             }
  701.         }
  702.     DisplaySelectCount();
  703.     
  704.     ForEachBond
  705.     {   /* Ignore ZoneBoth setting! */
  706.     flag = bptr->dstatom->flag & bptr->srcatom->flag;
  707.     if( flag & SelectFlag )
  708.     {   bptr->flag |= SelectFlag;
  709.         if( bptr->flag&DrawBondFlag )
  710.         {   DrawBonds = True;
  711.         if( bptr->flag & CylinderFlag )
  712.             if( bptr->irad>MaxBondRadius )
  713.             MaxBondRadius = bptr->irad;
  714.         } 
  715.     } else bptr->flag &= ~(SelectFlag|DrawBondFlag);
  716.     }
  717.  
  718.     ForEachBack
  719.     {   /* Ignore ZoneBoth setting! */
  720.         flag = bptr->dstatom->flag & bptr->srcatom->flag;
  721.         if( !(flag&SelectFlag) )
  722.             bptr->flag &= ~(SelectFlag|DrawBondFlag);
  723.     }
  724.  
  725.     if( DrawRibbon )
  726.     {   DrawRibbon = False;
  727.         for( chain=Database->clist; chain; chain=chain->cnext )
  728.             for( group=chain->glist; group; group=group->gnext )
  729.                 if( group->flag & DrawKnotFlag )
  730.                 {   for( ptr=group->alist; ptr; ptr=ptr->anext )
  731.                         if( IsAlphaCarbon(ptr->refno) ||
  732.                             IsSugarPhosphate(ptr->refno) )
  733.                         {   if( !(ptr->flag&SelectFlag) )
  734.                                 group->flag &= ~DrawKnotFlag;
  735.                             break;
  736.                         }
  737.                     if( group->flag & DrawKnotFlag ) 
  738.                         DrawRibbon = True;
  739.                 }
  740.     }
  741.  
  742.     DetermineClipping();
  743.     VoxelsClean = False;
  744.     BucketFlag = False;
  745. }
  746.  
  747.  
  748. void SelectZoneExpr( expr )
  749.     Expr *expr;
  750. {
  751.     register Bond __far *bptr;
  752.  
  753.     if( !Database )
  754.         return;
  755.  
  756.     SelectCount = 0;
  757.     for( QChain=Database->clist; QChain; QChain=QChain->cnext )
  758.         for( QGroup=QChain->glist; QGroup; QGroup=QGroup->gnext )
  759.             for( QAtom=QGroup->alist; QAtom; QAtom=QAtom->anext )
  760.                 if( EvaluateExpr(expr) )
  761.                 {   QAtom->flag |= SelectFlag;
  762.                     SelectCount++;
  763.                 } else QAtom->flag &= ~SelectFlag;
  764.     DisplaySelectCount();
  765.  
  766.     if( ZoneBoth )
  767.     {   ForEachBond
  768.            if( (bptr->srcatom->flag&bptr->dstatom->flag) & SelectFlag )
  769.            {   bptr->flag |= SelectFlag;
  770.            } else bptr->flag &= ~SelectFlag;
  771.     } else
  772.         ForEachBond
  773.            if( (bptr->srcatom->flag|bptr->dstatom->flag) & SelectFlag )
  774.            {   bptr->flag |= SelectFlag;
  775.            } else bptr->flag &= ~SelectFlag;
  776. }
  777.  
  778.  
  779. void RestrictZoneExpr( expr )
  780.     Expr *expr;
  781. {
  782.     register Bond __far *bptr;
  783.     register Chain __far *chain;
  784.     register Group __far *group;
  785.     register Atom __far *ptr;
  786.     register int flag;
  787.  
  788.     if( !Database )
  789.         return;
  790.  
  791.     DrawAtoms = False;   MaxAtomRadius = 0;
  792.     DrawBonds = False;   MaxBondRadius = 0;
  793.     DrawLabels = False;
  794.  
  795.     SelectCount = 0;
  796.     for( QChain=Database->clist; QChain; QChain=QChain->cnext )
  797.         for( QGroup=QChain->glist; QGroup; QGroup=QGroup->gnext )
  798.             for( QAtom=QGroup->alist; QAtom; QAtom=QAtom->anext )
  799.                 if( EvaluateExpr(expr) )
  800.                 {   QAtom->flag |= SelectFlag;
  801.                     SelectCount++;
  802.  
  803.                     if( QAtom->flag & SphereFlag )
  804.                     {   DrawAtoms = True;
  805.                         if( QAtom->irad>MaxAtomRadius )
  806.                             MaxAtomRadius = QAtom->irad;
  807.                     }
  808.                     if( QAtom->label )
  809.                         DrawLabels = True;
  810.  
  811.                 }  else 
  812.                 {   QAtom->flag &= ~(SelectFlag|SphereFlag);
  813.                     if( QAtom->label )
  814.                     {   DeleteLabel( (Label*)QAtom->label );
  815.                         QAtom->label = (void*)0;
  816.                     }
  817.                 }
  818.     DisplaySelectCount();
  819.  
  820.     ForEachBond
  821.     {   /* Ignore ZoneBoth setting! */
  822.         flag = bptr->dstatom->flag & bptr->srcatom->flag;
  823.         if( flag & SelectFlag )
  824.         {   bptr->flag |= SelectFlag;
  825.             if( bptr->flag & CylinderFlag )
  826.             {   DrawBonds = True;
  827.                 if( bptr->irad>MaxBondRadius )
  828.                     MaxBondRadius = bptr->irad;
  829.             } else if( bptr->flag&WireFlag )
  830.                 DrawBonds = True;
  831.         } else bptr->flag &= ~(SelectFlag|DrawBondFlag);
  832.     }
  833.  
  834.     ForEachBack
  835.     {   /* Ignore ZoneBoth setting! */
  836.         flag = bptr->dstatom->flag & bptr->srcatom->flag;
  837.         if( !(flag&SelectFlag) )
  838.             bptr->flag &= ~(SelectFlag|DrawBondFlag);
  839.     }
  840.  
  841.     if( DrawRibbon )
  842.     {   DrawRibbon = False;
  843.         for( chain=Database->clist; chain; chain=chain->cnext )
  844.             for( group=chain->glist; group; group=group->gnext )
  845.                 if( group->flag & DrawKnotFlag )
  846.                 {   for( ptr=group->alist; ptr; ptr=ptr->anext )
  847.                         if( IsAlphaCarbon(ptr->refno) ||
  848.                             IsSugarPhosphate(ptr->refno) )
  849.                         {   if( !(ptr->flag&SelectFlag) )
  850.                                 group->flag &= ~DrawKnotFlag;
  851.                             break;
  852.                         }
  853.                     if( group->flag & DrawKnotFlag )
  854.                         DrawRibbon = True;
  855.                 }
  856.     }
  857.  
  858.     DetermineClipping();
  859.     VoxelsClean = False;
  860.     BucketFlag = False;
  861. }
  862.  
  863.  
  864.  
  865. int DefineShade( r, g, b )
  866.     unsigned char r, g, b;
  867. {
  868.     register int d,dr,dg,db;
  869.     register int dist,best;
  870.     register int i;
  871.  
  872.     /* Already defined! */
  873.     for( i=0; i<LastShade; i++ )
  874.     if( Shade[i].refcount )
  875.         if( (Shade[i].r==r)&&(Shade[i].g==g)&&(Shade[i].b==b) )
  876.         return(i);
  877.  
  878.     /* Allocate request */
  879.     for( i=0; i<LastShade; i++ )
  880.      if( !Shade[i].refcount )
  881.      {   Shade[i].r = r;
  882.          Shade[i].g = g;
  883.          Shade[i].b = b;
  884.          Shade[i].refcount = 0;
  885.          return(i);
  886.      }
  887.  
  888.     if( CommandActive )
  889.     WriteChar('\n');
  890.     WriteString("Warning: Unable to allocate shade!\n");
  891.     CommandActive = False;
  892.  
  893.     /* To avoid lint warning! */
  894.     best = dist = 0;
  895.  
  896.     /* Nearest match */
  897.     for( i=0; i<LastShade; i++ )
  898.     {   dr = Shade[i].r - r;
  899.     dg = Shade[i].g - g;
  900.     db = Shade[i].b - b;
  901.     d = dr*dr + dg*dg + db*db;
  902.     if( !i || (d<dist) )
  903.     {   dist = d;
  904.         best = i;
  905.     }
  906.     }
  907.     return( best );
  908. }
  909.  
  910.  
  911. void ScaleColourMap( count )
  912.     int count;
  913. {
  914.     register Real hue;
  915.     register int fract, sextant;
  916.     register int i, r, g, b;
  917.  
  918.     ScaleCount=0;
  919.     for( i=0; i<LastShade; i++ )
  920.     if( !Shade[i].refcount )
  921.         ScaleCount++;
  922.  
  923.     /* If there are no shades free! */
  924.     if( !ScaleCount ) ScaleCount = LastShade;
  925.  
  926.     if( count && (count<ScaleCount) )
  927.     ScaleCount = count;
  928.  
  929.     for( i=0; i<ScaleCount; i++ )
  930.     {   sextant = (int)(hue = (4.0*i)/(ScaleCount-1));
  931.     fract = (int)(255.0*(hue-sextant));
  932.  
  933.     switch( sextant )
  934.     {   case(0): r = 0;         g = fract;     b = 255;         break;
  935.         case(1): r = 0;         g = 255;       b = 255-fract;   break;
  936.         case(2): r = fract;     g = 255;       b = 0;           break;
  937.         case(3): r = 255;       g = 255-fract; b = 0;           break;
  938.         default: r = 255;       g = 0;         b = 0;
  939.     }
  940.     ScaleRef[i].r = r;
  941.     ScaleRef[i].g = g;
  942.     ScaleRef[i].b = b;
  943.     ScaleRef[i].shade = 0;
  944.     ScaleRef[i].col = 0;
  945.     }
  946. }
  947.  
  948.  
  949. static void SetLutEntry( i, r, g, b )
  950.     int i, r, g, b;
  951. {
  952.     ULut[i] = True;
  953.     RLut[i] = r;
  954.     GLut[i] = g;
  955.     BLut[i] = b;
  956.  
  957. #ifdef EIGHTBIT
  958. #ifdef NEXT
  959.     Lut[i] = (r + (g<<1) + b)>>2;
  960. #else
  961.     Lut[i] = i;
  962. #endif
  963. #else
  964. #ifdef SIXTEENBIT
  965.     {
  966.     int s;
  967.     /*  adjust brightness at expense of color   */
  968.     s = ((r + g + b)>>4) - (r>>4) - (g>>4) - (b>>4);
  969.     while (s>0) {
  970.         if (b<255) { b++; if (!(b&15) && !(--s)) break; }
  971.         if (g<255) { g++; if (!(g&15) && !(--s)) break; }
  972.         if (r<255) { r++; if (!(r&15) && !(--s)) break; }
  973.         if (r==255 && g==255 && b==255) break;
  974.     }
  975.     /* Use cast to make byte order (endian) independent */
  976.     i<<=1;
  977.     ((Byte *)Lut)[i] = (r&240) | (g>>4);
  978.     ((Byte *)Lut)[i+1] = (b&240);
  979.     }
  980. #else
  981.     /* Use cast to make byte order (endian) independent */
  982.     i<<=2;
  983.     ((Byte *)Lut)[i] = r;
  984.     ((Byte *)Lut)[i+1] = g;
  985.     ((Byte *)Lut)[i+2] = b;
  986. #endif
  987. #endif
  988. }
  989.  
  990.  
  991. static Real Power( x, y )
  992.     Real x; int y;
  993. {
  994.     register Real result;
  995.  
  996.     result = x;
  997.     while( y>1 )
  998.     {   if( y&1 ) { result *= x; y--; }
  999.     else { result *= result; y>>=1; }
  1000.     }
  1001.     return( result );
  1002. }
  1003.  
  1004.  
  1005. void DefineColourMap()
  1006. {
  1007.     register Real diffuse;
  1008.     register Real temp, inten;
  1009.     register int col, r, g, b;
  1010.     register int i, j, k;
  1011.  
  1012.     for( i=0; i<LutSize; i++ )
  1013.     ULut[i] = False;
  1014.  
  1015.     if( !DisplayMode )
  1016.     {   SetLutEntry(BackCol,BackR,BackG,BackB);
  1017.     SetLutEntry(LabelCol,LabR,LabG,LabB);
  1018.     SetLutEntry(BoxCol,BoxR,BoxG,BoxB);
  1019.     } else SetLutEntry(BackCol,80,80,80);
  1020.  
  1021.  
  1022.     diffuse = 1.0 - Ambient;
  1023.     for( i=0; i<ColourDepth; i++ )
  1024.     {   temp = (Real)i/ColourMask;
  1025.     inten = diffuse*temp + Ambient;
  1026.  
  1027.     if( DisplayMode )
  1028.     {   /* Unselected [40,40,255] */
  1029.         /* Selected   [255,160,0]  */
  1030.         r = (int)(255*inten);
  1031.         g = (int)(160*inten);
  1032.         b = (int)(40*inten);
  1033.  
  1034.             /* Avoid Borland Compiler Warning! */
  1035.             /* Shade2Colour(0) == FirstCol     */
  1036.         SetLutEntry( FirstCol+i, b, b, r );
  1037.         SetLutEntry( Shade2Colour(1)+i, r, g, 0 );
  1038.  
  1039.     } else 
  1040.     {   if( FakeSpecular )
  1041.         {   temp = Power(temp,SpecPower);
  1042.         inten *= 1.0 - temp;
  1043.         k = (int)(255*temp);
  1044.         }
  1045.  
  1046.         for( j=0; j<LastShade; j++ )
  1047.         if( Shade[j].refcount )
  1048.         {   col = Shade2Colour(j);
  1049.             r = (int)(Shade[j].r*inten); 
  1050.             g = (int)(Shade[j].g*inten);
  1051.             b = (int)(Shade[j].b*inten);
  1052.  
  1053.             if( FakeSpecular )
  1054.             {   r += k;
  1055.             g += k;
  1056.             b += k;
  1057.             }
  1058.             SetLutEntry( col+i, r, g, b );
  1059.         }
  1060.     }
  1061.     }
  1062.  
  1063.     if( Interactive )
  1064.     AllocateColourMap();
  1065. }
  1066.  
  1067.  
  1068. void ResetColourMap()
  1069. {
  1070.     register int i;
  1071.  
  1072. #ifdef EIGHTBIT
  1073.     for( i=0; i<256; i++ )
  1074.     ULut[i] = False;
  1075. #endif
  1076.  
  1077.     SpecPower = 8;
  1078.     FakeSpecular = False;
  1079.     Ambient = DefaultAmbient;
  1080.     BackR = BackG = BackB = 0;
  1081.     BoxR = BoxG = BoxB = 255;
  1082.     LabR = LabG = LabB = 255;
  1083.     for( i=0; i<LastShade; i++ )
  1084.     Shade[i].refcount = 0;
  1085.     ScaleCount = 0;
  1086. }
  1087.  
  1088.  
  1089. void ColourBondNone()
  1090. {
  1091.     register Bond __far *bptr;
  1092.  
  1093.     if( Database )
  1094.     ForEachBond
  1095.         if( (bptr->flag&SelectFlag) && bptr->col )
  1096.         {   Shade[Colour2Shade(bptr->col)].refcount--;
  1097.         bptr->col = 0;
  1098.         }
  1099. }
  1100.  
  1101.  
  1102. void ColourBondAttrib( r, g, b )
  1103.     int r, g, b;
  1104. {
  1105.     register Bond __far *bptr;
  1106.     register int shade,col;
  1107.  
  1108.     if( Database )
  1109.     {   ForEachBond
  1110.         if( (bptr->flag&SelectFlag) && bptr->col )
  1111.         Shade[Colour2Shade(bptr->col)].refcount--;
  1112.  
  1113.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1114.     col = Shade2Colour(shade);
  1115.  
  1116.     ForEachBond
  1117.         if( bptr->flag&SelectFlag )
  1118.         {   Shade[shade].refcount++;
  1119.         bptr->col = col;
  1120.         }
  1121.     }
  1122. }
  1123.  
  1124.  
  1125. void ColourBackNone()
  1126. {
  1127.     register Chain __far *chain;
  1128.     register Bond __far *bptr;
  1129.     register int flag;
  1130.  
  1131.     if( Database )
  1132.     ForEachBack
  1133.     {   flag = ZoneBoth? bptr->dstatom->flag & bptr->srcatom->flag
  1134.                : bptr->dstatom->flag | bptr->srcatom->flag;
  1135.  
  1136.         if( flag&SelectFlag )
  1137.         {   bptr->flag |= SelectFlag;
  1138.         if( bptr->col )
  1139.         {   Shade[Colour2Shade(bptr->col)].refcount--;
  1140.             bptr->col = 0;
  1141.         }
  1142.         } else bptr->flag &= ~SelectFlag;
  1143.     }
  1144. }
  1145.  
  1146.  
  1147. void ColourBackAttrib( r, g, b )
  1148.     int r, g, b;
  1149. {
  1150.     register int shade,col;
  1151.     register Chain __far *chain;
  1152.     register Bond __far *bptr;
  1153.  
  1154.     if( Database )
  1155.     {   ColourBackNone();
  1156.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1157.     col = Shade2Colour(shade);
  1158.  
  1159.     ForEachBack
  1160.         if( bptr->flag&SelectFlag )
  1161.         {   Shade[shade].refcount++;
  1162.         bptr->col = col;
  1163.         }
  1164.     }
  1165. }
  1166.  
  1167.  
  1168. void ColourHBondNone( hbonds )
  1169.     int hbonds;
  1170. {
  1171.     register HBond __far *list;
  1172.     register HBond __far *ptr;
  1173.     register Atom __far *src;
  1174.     register Atom __far *dst;
  1175.  
  1176.     if( !Database )
  1177.     return;
  1178.  
  1179.     list = hbonds? Database->hlist : Database->slist;
  1180.  
  1181.     if( ZoneBoth )
  1182.     {   for( ptr=list; ptr; ptr=ptr->hnext )
  1183.     {   src = ptr->src;  dst = ptr->dst;
  1184.  
  1185.         if( (src->flag&dst->flag) & SelectFlag )
  1186.         {   ptr->flag |= SelectFlag;
  1187.         if( ptr->col )
  1188.         {   Shade[Colour2Shade(ptr->col)].refcount--;
  1189.             ptr->col = 0;
  1190.         }
  1191.         } else ptr->flag &= ~SelectFlag;
  1192.     }
  1193.     } else
  1194.     for( ptr=list; ptr; ptr=ptr->hnext )
  1195.     {   src = ptr->src;  dst = ptr->dst;
  1196.  
  1197.         if( (src->flag|dst->flag) & SelectFlag )
  1198.         {   ptr->flag |= SelectFlag;
  1199.         if( ptr->col )
  1200.         {   Shade[Colour2Shade(ptr->col)].refcount--;
  1201.             ptr->col = 0;
  1202.         }
  1203.         } else ptr->flag &= ~SelectFlag;
  1204.     }
  1205. }
  1206.  
  1207. void ColourHBondType()
  1208. {
  1209.     register HBond __far *ptr;
  1210.     register ShadeRef *ref;
  1211.     register int i;
  1212.  
  1213.     if( !Database ) return;
  1214.     for( i=0; i<7; i++ )
  1215.     HBondShade[i].col = 0;
  1216.  
  1217.     if( InfoHBondCount<0 )
  1218.     {   CalcHydrogenBonds();
  1219.     } else ColourHBondNone( True );
  1220.  
  1221.     for( ptr=Database->hlist; ptr; ptr=ptr->hnext )
  1222.     if( ptr->flag & SelectFlag )
  1223.     {   switch( ptr->offset )
  1224.         {   case(  2 ):  ref = HBondShade;     break;
  1225.         case(  3 ):  ref = HBondShade+1;   break;
  1226.         case(  4 ):  ref = HBondShade+2;   break;
  1227.         case(  5 ):  ref = HBondShade+3;   break;
  1228.         case( -3 ):  ref = HBondShade+4;   break;
  1229.         case( -4 ):  ref = HBondShade+5;   break;
  1230.         default:     ref = HBondShade+6;   break;
  1231.         }
  1232.  
  1233.         if( !ref->col )
  1234.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1235.         ref->col = Shade2Colour(ref->shade);
  1236.         }
  1237.         Shade[ref->shade].refcount++;
  1238.         ptr->col = (Byte)ref->col;
  1239.     }
  1240. }
  1241.  
  1242.  
  1243. void ColourHBondAttrib( hbonds, r, g, b )
  1244.     int hbonds, r, g, b;
  1245. {
  1246.     register HBond __far *list;
  1247.     register HBond __far *ptr;
  1248.     register int col,shade;
  1249.  
  1250.     if( !Database )
  1251.     return;
  1252.  
  1253.     if( hbonds )
  1254.     {   if( InfoHBondCount<0 )
  1255.     {   CalcHydrogenBonds();
  1256.     } else ColourHBondNone(True);
  1257.     } else
  1258.     if( InfoSSBondCount<0 )
  1259.     {   FindDisulphideBridges();
  1260.     } else ColourHBondNone(False);
  1261.  
  1262.  
  1263.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1264.     col = Shade2Colour(shade);
  1265.  
  1266.     list = hbonds? Database->hlist : Database->slist;
  1267.     for( ptr=list; ptr; ptr=ptr->hnext )
  1268.     if( ptr->flag & SelectFlag )
  1269.     {   Shade[shade].refcount++;
  1270.         ptr->col = col;
  1271.     }
  1272. }
  1273.  
  1274.  
  1275. void ColourRibbonNone( flag )
  1276.     int flag;
  1277. {
  1278.     register Chain __far *chain;
  1279.     register Group __far *group;
  1280.     register Atom __far *aptr;
  1281.  
  1282.     if( !Database )
  1283.     return;
  1284.  
  1285.     if( InfoHelixCount<0 )
  1286.     return;
  1287.  
  1288.     for( chain=Database->clist; chain; chain=chain->cnext )
  1289.     for( group=chain->glist; group; group=group->gnext )
  1290.         {   aptr = FindGroupAtom(group,1);
  1291.         if( aptr && (aptr->flag&SelectFlag) )
  1292.         {   if( (flag&RibColInside) && group->col1 )
  1293.         {   Shade[Colour2Shade(group->col1)].refcount--;
  1294.             group->col1 = 0;
  1295.         }
  1296.         if( (flag&RibColOutside) && group->col2 )
  1297.         {   Shade[Colour2Shade(group->col2)].refcount--;
  1298.             group->col2 = 0;
  1299.         }
  1300.         }
  1301.         }
  1302. }
  1303.  
  1304.  
  1305. void ColourRibbonAttrib( flag, r, g, b )
  1306.     int flag, r, g, b;
  1307. {
  1308.     register int shade, col;
  1309.     register Chain __far *chain;
  1310.     register Group __far *group;
  1311.     register Atom __far *aptr;
  1312.  
  1313.     if( Database )
  1314.     {   if( InfoHelixCount >= 0 )
  1315.     {   ColourRibbonNone( flag );
  1316.     } else DetermineStructure(False);
  1317.  
  1318.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1319.     col = Shade2Colour(shade);
  1320.  
  1321.     for( chain=Database->clist; chain; chain=chain->cnext )
  1322.         for( group=chain->glist; group; group=group->gnext )
  1323.             {   aptr = FindGroupAtom(group,1);
  1324.         if( aptr && (aptr->flag&SelectFlag) )
  1325.         {   if( flag & RibColInside )
  1326.             {   Shade[shade].refcount++;
  1327.             group->col1 = col;
  1328.             }
  1329.             if( flag & RibColOutside )
  1330.             {   Shade[shade].refcount++;
  1331.             group->col2 = col;
  1332.             }
  1333.         }
  1334.             }
  1335.     }
  1336. }
  1337.  
  1338.  
  1339. void ColourMonitNone()
  1340. {
  1341.     register Monitor *ptr;
  1342.     register int flag;
  1343.  
  1344.     if( Database )
  1345.         for( ptr=MonitList; ptr; ptr=ptr->next )
  1346.             if( ptr->col )
  1347.             {   flag = ZoneBoth? ptr->src->flag & ptr->dst->flag
  1348.                                : ptr->src->flag | ptr->dst->flag;
  1349.                 if( flag & SelectFlag )
  1350.                 {   Shade[Colour2Shade(ptr->col)].refcount--;
  1351.                     ptr->col = 0;
  1352.                 }
  1353.             }
  1354. }
  1355.  
  1356.  
  1357. void ColourMonitAttrib( r, g, b )
  1358.     int r, g, b;
  1359. {
  1360.     register Monitor *ptr;
  1361.     register int shade,col;
  1362.     register int flag;
  1363.  
  1364.     if( !Database )
  1365.         return;
  1366.  
  1367.     ColourMonitNone();
  1368.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1369.     col = Shade2Colour(shade);
  1370.  
  1371.     for( ptr=MonitList; ptr; ptr=ptr->next )
  1372.     {   flag = ZoneBoth? ptr->src->flag & ptr->dst->flag 
  1373.                        : ptr->src->flag | ptr->dst->flag;
  1374.         if( flag & SelectFlag )
  1375.         {   Shade[shade].refcount++;
  1376.             ptr->col = col;
  1377.         }
  1378.     }
  1379. }
  1380.  
  1381.  
  1382. void ColourDotsAttrib( r, g, b )
  1383.     int r, g, b;
  1384. {
  1385.     register DotStruct __far *ptr;
  1386.     register int i,shade,col;
  1387.  
  1388.     if( Database )
  1389.     {   for( ptr=DotPtr; ptr; ptr=ptr->next )
  1390.         for( i=0; i<ptr->count; i++ )
  1391.         {    shade = Colour2Shade(ptr->col[i]);
  1392.          Shade[shade].refcount--;
  1393.         }
  1394.  
  1395.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1396.     col = Shade2Colour(shade);
  1397.     for( ptr=DotPtr; ptr; ptr=ptr->next )
  1398.         for( i=0; i<ptr->count; i++ )
  1399.         {   Shade[shade].refcount++;
  1400.         ptr->col[i] = col;
  1401.         }
  1402.     }
  1403. }
  1404.  
  1405.  
  1406. /* Coulomb's Law */
  1407. #define CoulombScale  ((Long)(1<<12))
  1408. int CalculatePotential( x, y, z )
  1409.     Long x, y, z;
  1410. {
  1411.     register Chain __far *chain;
  1412.     register Group __far *group;
  1413.     register Atom __far *ptr;
  1414.     register Long dx,dy,dz;
  1415.     register Long result;
  1416.     register Card dist;
  1417.     register Card max;
  1418.  
  1419.  
  1420.     /* Calculated charges have b-values < 0.0     */
  1421.     /* if( MinFun(MinMainTemp,MinHetaTemp) >= 0 ) */
  1422.     /*     CalculateCharges();                    */
  1423.  
  1424.     /* 8.0 Angstrom Cut Off */
  1425.     max = (Long)2000*2000;
  1426.  
  1427.     result = 0;
  1428.     ForEachAtom
  1429.     {   dx = ptr->xorg-x;
  1430.     if( (dist=dx*dx) < max )
  1431.     {   dy = ptr->yorg - y;
  1432.         if( (dist+=dy*dy) < max )
  1433.         {   dz = ptr->zorg - z;
  1434.         if( (dist+=dz*dz) < max )
  1435.             result += (CoulombScale*ptr->temp) / (int)isqrt(dist);
  1436.         }
  1437.     }
  1438.     }
  1439.     /* Dielectric Constant = 10.0 */
  1440.     /* (332.0*250.0)/(10.0*100.0) */
  1441.     result = (result*83)/CoulombScale;
  1442.     return( (int)result );
  1443. }
  1444.  
  1445.  
  1446. void ColourDotsPotential()
  1447. {
  1448.     register DotStruct __far *ptr;
  1449.     register int i,shade,result;
  1450.     register ShadeRef *ref;
  1451.  
  1452.     if( Database )
  1453.     {   for( i=0; i<8; i++ )
  1454.         PotentialShade[i].col = 0;
  1455.  
  1456.     /* Colour Dots None! */
  1457.     for( ptr=DotPtr; ptr; ptr=ptr->next )
  1458.         for( i=0; i<ptr->count; i++ )
  1459.         {    shade = Colour2Shade(ptr->col[i]);
  1460.          Shade[shade].refcount--;
  1461.         }
  1462.  
  1463.     for( ptr=DotPtr; ptr; ptr=ptr->next )
  1464.         for( i=0; i<ptr->count; i++ )
  1465.         {   result = CalculatePotential( ptr->xpos[i],
  1466.                          ptr->ypos[i],
  1467.                          ptr->zpos[i] );
  1468.  
  1469.         /* Determine Colour Bucket */
  1470.         if( result >= 0 )
  1471.         {   if( result > 10 )
  1472.             {      if( result > 24 )
  1473.                {      ref = PotentialShade + 0;
  1474.                } else ref = PotentialShade + 1;
  1475.             } else if( result > 3 )
  1476.                {      ref = PotentialShade + 2;
  1477.                } else ref = PotentialShade + 3;
  1478.         } else 
  1479.             if( result > -10 )
  1480.             {      if( result > -3 )
  1481.                {      ref = PotentialShade + 4;
  1482.                } else ref = PotentialShade + 5;
  1483.             } else if( result > -24 )
  1484.                {      ref = PotentialShade + 6;
  1485.                } else ref = PotentialShade + 7;
  1486.  
  1487.         if( !ref->col )
  1488.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1489.             ref->col = Shade2Colour(ref->shade);
  1490.         }
  1491.         Shade[ref->shade].refcount++;
  1492.         ptr->col[i] = ref->col;
  1493.         }
  1494.     }
  1495. }
  1496.  
  1497.  
  1498. static void ResetColourAttrib()
  1499. {
  1500.     register Chain __far *chain;
  1501.     register Group __far *group;
  1502.     register Atom __far *ptr;
  1503.  
  1504.     ForEachAtom
  1505.     if( (ptr->flag&SelectFlag) && ptr->col )
  1506.         Shade[Colour2Shade(ptr->col)].refcount--;
  1507. }
  1508.  
  1509.  
  1510. void MonoColourAttrib( r, g, b )
  1511.     int r, g, b;
  1512. {
  1513.     register int shade,col;
  1514.     register Chain __far *chain;
  1515.     register Group __far *group;
  1516.     register Atom __far *ptr;
  1517.  
  1518.     if( Database )
  1519.     {   ResetColourAttrib();
  1520.     shade = DefineShade((Byte)r,(Byte)g,(Byte)b);
  1521.     col = Shade2Colour(shade);
  1522.  
  1523.     ForEachAtom
  1524.         if( ptr->flag&SelectFlag )
  1525.         {   Shade[shade].refcount++;
  1526.         ptr->col = col;
  1527.         }
  1528.     }
  1529. }
  1530.  
  1531.  
  1532. void ScaleColourAttrib( attr )
  1533.     int attr;
  1534. {
  1535.     register ShadeRef *ref;
  1536.     register int count, attrno, factor;
  1537.     register Chain __far *chain;
  1538.     register Group __far *group;
  1539.     register Atom __far *ptr;
  1540.     register Long temp;
  1541.     register int i;
  1542.  
  1543.     if( !Database ) return;
  1544.  
  1545.     switch( attr )
  1546.     {   case(ChainAttr):   attrno = InfoChainCount;   
  1547.                factor = 1;
  1548.                break;
  1549.  
  1550.     case(GroupAttr):   factor = MinMainRes;
  1551.                attrno = MaxMainRes;
  1552.                if( HetaGroups && HetaGroupCount )
  1553.                {   if( MinHetaRes < factor )
  1554.                    factor = MinHetaRes;
  1555.                    if( MaxHetaRes > attrno )
  1556.                    attrno = MaxHetaRes;
  1557.                } 
  1558.                attrno -= (factor-1);
  1559.                break;
  1560.  
  1561.     case(ChargeAttr):
  1562.     case(TempAttr):    factor = MinMainTemp;
  1563.                attrno = MaxMainTemp;
  1564.                if( HetaGroups && HetaGroupCount )
  1565.                {   if( MinHetaTemp < factor )
  1566.                    factor = MinHetaTemp;
  1567.                    if( MaxHetaTemp > attrno )
  1568.                    attrno = MaxHetaTemp;
  1569.                }
  1570.                attrno -= (factor-1);
  1571.                break;
  1572.  
  1573.     default:           return;
  1574.     }
  1575.  
  1576.     if( attrno<2 )
  1577.     {   MonoColourAttrib(255,255,255);
  1578.     return;
  1579.     }
  1580.  
  1581.     ResetColourAttrib();
  1582.     ScaleColourMap(attrno);
  1583.  
  1584.     switch( attr )
  1585.     {    case(ChainAttr):
  1586.          count = 0;
  1587.          for( chain=Database->clist; chain; chain=chain->cnext )
  1588.          {   ref = &(ScaleRef[(count*ScaleCount)/attrno]);
  1589.              if( !(ref->col && Shade[ref->shade].refcount) )
  1590.              {   ref->shade = DefineShade(ref->r,ref->g,ref->b);
  1591.              ref->col = Shade2Colour(ref->shade);
  1592.              }
  1593.              for( group=chain->glist; group; group=group->gnext )
  1594.              for( ptr=group->alist; ptr; ptr=ptr->anext )
  1595.                  if( ptr->flag&SelectFlag )
  1596.                  {   Shade[ref->shade].refcount++;
  1597.                  ptr->col = ref->col;
  1598.                  }
  1599.              count++;
  1600.          }
  1601.          break;
  1602.  
  1603.  
  1604.      case(GroupAttr):
  1605.          for( chain=Database->clist; chain; chain=chain->cnext )
  1606.              for( group=chain->glist; group; group=group->gnext )
  1607.              {   temp = (Long)ScaleCount*(group->serno-factor);
  1608.              i = (int)(temp/attrno);
  1609.  
  1610.              if( i >= ScaleCount )
  1611.              {   ref = ScaleRef + (ScaleCount-1);
  1612.              } else if( i >= 0 )
  1613.              {   ref = ScaleRef + i;
  1614.              } else ref = ScaleRef;
  1615.  
  1616.              if( !(ref->col && Shade[ref->shade].refcount) )
  1617.              {   ref->shade = DefineShade(ref->r,ref->g,ref->b);
  1618.                  ref->col = Shade2Colour(ref->shade);
  1619.              }
  1620.  
  1621.              for( ptr=group->alist; ptr; ptr=ptr->anext )
  1622.                  if( ptr->flag&SelectFlag )
  1623.                  {   Shade[ref->shade].refcount++;
  1624.                  ptr->col = ref->col;
  1625.                  }
  1626.              }
  1627.          break;
  1628.  
  1629.  
  1630.      case(TempAttr):
  1631.          ForEachAtom
  1632.              if( ptr->flag&SelectFlag )
  1633.              {   i = (int)(((Long)ScaleCount*(ptr->temp-factor))
  1634.                     /attrno);
  1635.  
  1636.              if( i >= ScaleCount )
  1637.              {   ref = ScaleRef + (ScaleCount-1);
  1638.              } else if( i >= 0 )
  1639.              {   ref = ScaleRef + i;
  1640.              } else ref = ScaleRef;
  1641.  
  1642.              if( !(ref->col && Shade[ref->shade].refcount) )
  1643.              {   ref->shade = DefineShade(ref->r,ref->g,ref->b);
  1644.                  ref->col = Shade2Colour(ref->shade);
  1645.              }
  1646.              Shade[ref->shade].refcount++;
  1647.              ptr->col = ref->col;
  1648.              }
  1649.          break;
  1650.  
  1651.     case(ChargeAttr):
  1652.         ForEachAtom
  1653.              if( ptr->flag&SelectFlag )
  1654.              {   i = (int)(((Long)ScaleCount*(ptr->temp-factor))
  1655.                     /attrno);
  1656.  
  1657.              if( i <= 0 )
  1658.              {   ref = ScaleRef + (ScaleCount-1);
  1659.              } else if( i < ScaleCount )
  1660.              {   ref = ScaleRef + ((ScaleCount-1)-i);
  1661.              } else ref = ScaleRef;
  1662.  
  1663.              if( !(ref->col && Shade[ref->shade].refcount) )
  1664.              {   ref->shade = DefineShade(ref->r,ref->g,ref->b);
  1665.                  ref->col = Shade2Colour(ref->shade);
  1666.              }
  1667.              Shade[ref->shade].refcount++;
  1668.              ptr->col = ref->col;
  1669.              }
  1670.          break;
  1671.     }
  1672. }
  1673.  
  1674.  
  1675.  
  1676. static int MatchNumber( len, value, mask )
  1677.     int len, value;
  1678.     char *mask;
  1679. {
  1680.     register char digit, template;
  1681.     register int result;
  1682.     register int i;
  1683.  
  1684.     result = True;
  1685.     for( i=0; i<len; i++ )
  1686.     {   digit = (value%10) + '0';
  1687.     template = mask[len-i];
  1688.     if( template==' ' )
  1689.     {   if( value ) result = False;
  1690.     } else if( !MatchChar(template,digit) )
  1691.         result = False;
  1692.     value/=10;
  1693.     }
  1694.     return( result );
  1695. }
  1696.  
  1697.  
  1698. void UserMaskAttrib( fields )
  1699.     int fields;
  1700. {
  1701.     register MaskDesc *mptr;
  1702.     register char *temp, *name;
  1703.     register int shade, change;
  1704.     register int i, rad, match;
  1705.  
  1706.     register Chain __far *chain;
  1707.     register Group __far *group;
  1708.     register Atom __far *ptr;
  1709.  
  1710.  
  1711.     if( !Database ) return;
  1712.  
  1713.     if( !MaskCount )
  1714.     {   if( CommandActive )
  1715.         WriteChar('\n');
  1716.     WriteString("Warning: No user supplied colour records!\n");
  1717.     CommandActive = False;
  1718.     return;
  1719.     }
  1720.  
  1721.     change = False;
  1722.     ResetColourAttrib();
  1723.     if( fields&MaskColourFlag )
  1724.     for( i=0; i<MaskCount; i++ )
  1725.         MaskShade[i] = -1;
  1726.  
  1727.     if( fields&MaskRadiusFlag )
  1728.     {   MaxAtomRadius = 0;
  1729.     DrawAtoms = False;
  1730.     }
  1731.  
  1732.  
  1733.     ForEachAtom
  1734.     if( ptr->flag&SelectFlag )
  1735.     {   for( i=0; i<MaskCount; i++ )
  1736.     {   mptr = UserMask+i;
  1737.         temp = mptr->mask;
  1738.         match = True;
  1739.  
  1740.         if( !MatchChar(temp[13],chain->ident) ) match=False;
  1741.         if( !MatchChar(temp[9],ptr->altl) )     match=False;
  1742.  
  1743.         /* Atom Name */
  1744.         if( match )
  1745.         {   name = ElemDesc[ptr->refno];
  1746.         if( !MatchChar(temp[5],name[0]) ) match=False;
  1747.         if( !MatchChar(temp[6],name[1]) ) match=False;
  1748.         if( !MatchChar(temp[7],name[2]) ) match=False;
  1749.         if( !MatchChar(temp[8],name[3]) ) match=False;
  1750.         }
  1751.  
  1752.         /* Group Name */
  1753.         if( match )
  1754.         {   name = Residue[group->refno];
  1755.         if( !MatchChar(temp[10],name[0]) ) match=False;
  1756.         if( !MatchChar(temp[11],name[1]) ) match=False;
  1757.         if( !MatchChar(temp[12],name[2]) ) match=False;
  1758.         }
  1759.  
  1760.  
  1761.         if( match && (mptr->flags&SerNoFlag) )
  1762.         match = MatchNumber(4,ptr->serno,&temp[0]);
  1763.         if( match && (mptr->flags&ResNoFlag) )
  1764.         match = MatchNumber(3,group->serno,&temp[14]);
  1765.         if( match ) break;
  1766.     }
  1767.  
  1768.     if( fields&MaskColourFlag )
  1769.     {   if( match )
  1770.         {   if( MaskShade[i] == -1 )
  1771.         {   MaskShade[i] = DefineShade(mptr->r,mptr->g,mptr->b);
  1772.             MaskColour[i] = Shade2Colour(MaskShade[i]);
  1773.         }
  1774.         Shade[MaskShade[i]].refcount++;
  1775.         ptr->col = MaskColour[i];
  1776.         } else
  1777.         {   shade = DefineShade(255,255,255);
  1778.         ptr->col = Shade2Colour(shade);
  1779.         Shade[shade].refcount++;
  1780.         }
  1781.     }
  1782.  
  1783.     if( fields&MaskRadiusFlag )
  1784.     {   rad = match? mptr->radius : 375;
  1785.         ptr->irad = (int)(Scale*rad);
  1786.         ptr->flag |= SphereFlag;
  1787.         ptr->radius = rad;
  1788.  
  1789.         if( ptr->irad>MaxAtomRadius )
  1790.         MaxAtomRadius = ptr->irad;
  1791.         change = True;
  1792.     }
  1793.     } else if( ptr->flag&SphereFlag )
  1794.     {   DrawAtoms = True;
  1795.     if( ptr->irad>MaxAtomRadius )
  1796.         MaxAtomRadius = ptr->irad;
  1797.     }
  1798.  
  1799.     if( change )
  1800.     {   DrawAtoms = True;
  1801.     DetermineClipping();
  1802.     VoxelsClean = False;
  1803.     BucketFlag = False;
  1804.     }
  1805. }
  1806.  
  1807.  
  1808. void CPKColourAttrib()
  1809. {
  1810.     register ShadeRef *ref;
  1811.     register Chain __far *chain;
  1812.     register Group __far *group;
  1813.     register Atom __far *ptr;
  1814.     register int i;
  1815.  
  1816.     if( !Database ) return;
  1817.     for( i=0; i<CPKMAX; i++ )
  1818.     CPKShade[i].col = 0;
  1819.     ResetColourAttrib();
  1820.  
  1821.  
  1822.     ForEachAtom
  1823.     if( ptr->flag&SelectFlag )
  1824.     {   ref = CPKShade + Element[ptr->elemno].cpkcol;
  1825.  
  1826.         if( !ref->col )
  1827.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1828.         ref->col = Shade2Colour(ref->shade);
  1829.         }
  1830.         Shade[ref->shade].refcount++;
  1831.         ptr->col = ref->col;
  1832.     }
  1833. }
  1834.  
  1835.  
  1836. void AminoColourAttrib()
  1837. {
  1838.     register ShadeRef *ref;
  1839.     register Chain __far *chain;
  1840.     register Group __far *group;
  1841.     register Atom __far *ptr;
  1842.     register int i;
  1843.  
  1844.     if( !Database ) return;
  1845.     for( i=0; i<13; i++ )
  1846.     AminoShade[i].col = 0;
  1847.     ResetColourAttrib();
  1848.  
  1849.     ForEachAtom
  1850.     if( ptr->flag&SelectFlag )
  1851.     {   if( IsAmino(group->refno) )
  1852.         {   ref = AminoShade + AminoIndex[group->refno];
  1853.         } else ref = AminoShade+12;
  1854.  
  1855.         if( !ref->col )
  1856.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1857.         ref->col = Shade2Colour(ref->shade);
  1858.         }
  1859.         Shade[ref->shade].refcount++;
  1860.         ptr->col = ref->col;
  1861.     }
  1862. }
  1863.  
  1864.  
  1865. void ShapelyColourAttrib()
  1866. {
  1867.     register ShadeRef *ref;
  1868.     register Chain __far *chain;
  1869.     register Group __far *group;
  1870.     register Atom __far *ptr;
  1871.     register int i;
  1872.  
  1873.     if( !Database ) return;
  1874.     for( i=0; i<30; i++ )
  1875.     Shapely[i].col = 0;
  1876.     ResetColourAttrib();
  1877.  
  1878.     ForEachAtom
  1879.     if( ptr->flag&SelectFlag )
  1880.     {   if( IsAminoNucleo(group->refno) )
  1881.         {   ref = Shapely + group->refno;
  1882.         } else ref = Shapely+30;
  1883.  
  1884. /*  Original Colour Scheme
  1885.  *
  1886.  *  ref = &(Shapely[26]);
  1887.  *  if( IsNucleo(group->refno) )
  1888.  *  {   ref = Shapely + group->refno;
  1889.  *  } else if( IsShapelyBackbone(ptr->refno) )
  1890.  *  {   ref = &(Shapely[24]);
  1891.  *  } else if( IsShapelySpecial(ptr->refno) )
  1892.  *  {   ref = &(Shapely[25]);
  1893.  *  } else if( IsAmino(group->refno) )
  1894.  *      ref = Shapely + group->refno;
  1895.  */
  1896.  
  1897.         if( !ref->col )
  1898.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1899.         ref->col = Shade2Colour(ref->shade);
  1900.         }
  1901.         Shade[ref->shade].refcount++;
  1902.         ptr->col = ref->col;
  1903.     }
  1904. }
  1905.  
  1906.  
  1907. void StructColourAttrib()
  1908. {
  1909.     register ShadeRef *ref;
  1910.     register Chain __far *chain;
  1911.     register Group __far *group;
  1912.     register Atom __far *ptr;
  1913.     register int i;
  1914.  
  1915.     if( !Database )
  1916.     return;
  1917.  
  1918.     if( InfoHelixCount<0 )
  1919.     DetermineStructure(False);
  1920.  
  1921.     for( i=0; i<4; i++ )
  1922.     StructShade[i].col = 0;
  1923.     ResetColourAttrib();
  1924.  
  1925.     ForEachAtom
  1926.     if( ptr->flag&SelectFlag )
  1927.     {   if( group->struc & HelixFlag )
  1928.         {   ref = StructShade+1;
  1929.         } else if( group->struc & SheetFlag )
  1930.         {   ref = StructShade+2;
  1931.         } else if( group->struc & TurnFlag )
  1932.         {   ref = StructShade+3;
  1933.         } else ref = StructShade;
  1934.  
  1935.         if( !ref->col )
  1936.         {   ref->shade = DefineShade( ref->r, ref->g, ref->b );
  1937.         ref->col = Shade2Colour(ref->shade);
  1938.         }
  1939.         Shade[ref->shade].refcount++;
  1940.         ptr->col = ref->col;
  1941.     }
  1942. }
  1943.  
  1944.  
  1945.  
  1946. int IsCPKColour( ptr )
  1947.     Atom __far *ptr;
  1948. {
  1949.     register ShadeRef *cpk;
  1950.     register ShadeDesc *col;
  1951.  
  1952.     cpk = CPKShade + Element[ptr->elemno].cpkcol;
  1953.     col = Shade + Colour2Shade(ptr->col);
  1954.     return( (col->r==cpk->r) && 
  1955.         (col->g==cpk->g) && 
  1956.         (col->b==cpk->b) );
  1957. }
  1958.  
  1959.  
  1960. int IsVDWRadius( ptr )
  1961.     Atom __far *ptr;
  1962. {
  1963.     register int rad;
  1964.  
  1965.     if( ptr->flag & SphereFlag )
  1966.     {   rad = ElemVDWRadius( ptr->elemno );
  1967.         return( ptr->radius == rad );
  1968.     } else return( False );
  1969. }
  1970.  
  1971.  
  1972.  
  1973. void InitialTransform()
  1974. {
  1975.     register Card dist,max;
  1976.     register double fdist,fmax;
  1977.     register Chain __far *chain;
  1978.     register Group __far *group;
  1979.     register Atom __far *ptr;
  1980.     register Card ax, ay, az;
  1981.     register Long dx, dy, dz;
  1982.  
  1983.  
  1984.     dx = MaxX-MinX;   OrigCX = (dx>>1)+MinX;
  1985.     dy = MaxY-MinY;   OrigCY = (dy>>1)+MinY;
  1986.     dz = MaxZ-MinZ;   OrigCZ = (dz>>1)+MinZ;
  1987.  
  1988.     MaxX -= OrigCX;   MinX -= OrigCX;
  1989.     MaxY -= OrigCY;   MinY -= OrigCY;
  1990.     MaxZ -= OrigCZ;   MinZ -= OrigCZ;
  1991.  
  1992.     SideLen = MaxFun(dx,dy);
  1993.     if( dz>SideLen ) SideLen = dz;
  1994.     SideLen += 1000;  Offset = SideLen>>1;
  1995.     XOffset = WRange;  YOffset = HRange;
  1996.     ZOffset = 10000;
  1997.  
  1998.     ForEachAtom
  1999.     {   ptr->xorg -= OrigCX;
  2000.         ptr->yorg -= OrigCY;
  2001.         ptr->zorg -= OrigCZ;
  2002.     }
  2003.  
  2004.     if( Offset > 37836 )
  2005.     {   fmax = 0.0;
  2006.         ForEachAtom
  2007.         {   ax = (Card)AbsFun(ptr->xorg);
  2008.             ay = (Card)AbsFun(ptr->yorg);
  2009.             az = (Card)AbsFun(ptr->zorg);
  2010.         fdist = (double)ax*ax + 
  2011.                     (double)ay*ay + 
  2012.                     (double)az*az;
  2013.         if( fdist > fmax )
  2014.             fmax = fdist;
  2015.         }
  2016.     } else
  2017.     {   max = 0;
  2018.         ForEachAtom
  2019.         {   ax = (Card)AbsFun(ptr->xorg);
  2020.             ay = (Card)AbsFun(ptr->yorg);
  2021.             az = (Card)AbsFun(ptr->zorg);
  2022.             dist = ax*ax + ay*ay + az*az;
  2023.             if( dist > max )
  2024.                 max = dist;
  2025.         }
  2026.         fmax = (double)max;
  2027.     }
  2028.  
  2029.  
  2030.     WorldRadius = (Card)sqrt(fmax);
  2031.     WorldSize = WorldRadius<<1;
  2032.     DScale = 1.0/(WorldSize+1000);
  2033.  
  2034.     /* MaxZoom*DScale*Range*500 == 118 */
  2035.     MaxZoom = 0.236*(WorldSize+1000)/Range;
  2036.     if( MaxZoom < 1.0 )
  2037.     {   DScale *= MaxZoom;
  2038.     MaxZoom = 1.0;
  2039.     }
  2040.     ZoomRange = Range;
  2041.     MaxZoom -= 1.0;
  2042. }
  2043.  
  2044.  
  2045. void ReviseInvMatrix()
  2046. {
  2047.     /* The inverse of a rotation matrix
  2048.      * is its transpose, and the inverse
  2049.      * of Scale is 1.0/Scale [IScale]!
  2050.      */
  2051.     InvX[0] = IScale*RotX[0];
  2052.     InvX[1] = IScale*RotY[0];
  2053.     InvX[2] = IScale*RotZ[0];
  2054.  
  2055.     InvY[0] = IScale*RotX[1];
  2056.     InvY[1] = IScale*RotY[1];
  2057.     InvY[2] = IScale*RotZ[1];
  2058.  
  2059.     InvZ[0] = IScale*RotX[2];
  2060.     InvZ[1] = IScale*RotY[2];
  2061.     InvZ[2] = IScale*RotZ[2];
  2062.     ShadowTransform();
  2063. }
  2064.  
  2065.  
  2066. void PrepareTransform()
  2067. {
  2068.     register Real theta, temp;
  2069.     register Real cost, sint;
  2070.     register Real x, y, z;
  2071.     register Real ncost;
  2072.  
  2073.     if( (ReDrawFlag&RFRotateX) && (DialValue[0]!=LastRX) )
  2074.     {   theta = PI*(DialValue[0]-LastRX);
  2075.     cost = cos(theta);  sint = sin(theta);
  2076.     LastRX = DialValue[0];
  2077.  
  2078.     y=RotY[0]; z=RotZ[0];
  2079.     RotY[0]=cost*y+sint*z; 
  2080.     RotZ[0]=cost*z-sint*y;
  2081.  
  2082.     y=RotY[1]; z=RotZ[1];
  2083.     RotY[1]=cost*y+sint*z;
  2084.     RotZ[1]=cost*z-sint*y;
  2085.  
  2086.     y=RotY[2]; z=RotZ[2];
  2087.     RotY[2]=cost*y+sint*z;
  2088.     RotZ[2]=cost*z-sint*y;
  2089.  
  2090.     if( CenX || CenY || CenZ )
  2091.     {   ncost = 1.0-cost;
  2092.         temp =  CenX*(ncost*RotY[0] + sint*RotZ[0]);
  2093.         temp += CenY*(ncost*RotY[1] + sint*RotZ[1]);
  2094.         temp += CenZ*(ncost*RotY[2] + sint*RotZ[2]);
  2095.         temp = DialValue[5] - (Scale*temp)/YRange;
  2096.  
  2097.         if( temp < -1.0 )
  2098.         {   DialValue[5] = -1.0;
  2099.         } else if( temp > 1.0 )
  2100.         {   DialValue[5] = 1.0;
  2101.         } else DialValue[5] = temp;
  2102.     }
  2103.     }
  2104.  
  2105.     if( (ReDrawFlag&RFRotateY) && (DialValue[1]!=LastRY) )
  2106.     {   theta = PI*(DialValue[1]-LastRY);
  2107.     cost = cos(theta);  sint = sin(theta);
  2108.     LastRY = DialValue[1];
  2109.  
  2110.     x=RotX[0]; z=RotZ[0];
  2111.     RotX[0]=cost*x+sint*z;
  2112.     RotZ[0]=cost*z-sint*x;
  2113.  
  2114.     x=RotX[1]; z=RotZ[1];
  2115.     RotX[1]=cost*x+sint*z;
  2116.     RotZ[1]=cost*z-sint*x;
  2117.  
  2118.     x=RotX[2]; z=RotZ[2];
  2119.     RotX[2]=cost*x+sint*z;
  2120.     RotZ[2]=cost*z-sint*x;
  2121.  
  2122.     if( CenX || CenY || CenZ )
  2123.     {   ncost = 1.0-cost;
  2124.         temp =  CenX*(ncost*RotX[0] + sint*RotZ[0]);
  2125.         temp += CenY*(ncost*RotX[1] + sint*RotZ[1]);
  2126.         temp += CenZ*(ncost*RotX[2] + sint*RotZ[2]);
  2127.         temp = DialValue[4] - (Scale*temp)/XRange;
  2128.  
  2129.         if( temp < -1.0 )
  2130.         {   DialValue[4] = -1.0;
  2131.         } else if( temp > 1.0 )
  2132.         {   DialValue[4] = 1.0;
  2133.         } else DialValue[4] = temp;
  2134.     }
  2135.     }
  2136.  
  2137.     if( (ReDrawFlag&RFRotateZ) && (DialValue[2]!=LastRZ) )
  2138.     {   theta = PI*(DialValue[2]-LastRZ);
  2139.     cost = cos(theta);  sint = sin(theta);
  2140.     LastRZ = DialValue[2];
  2141.  
  2142.     x=RotX[0]; y=RotY[0];
  2143.     RotX[0]=cost*x-sint*y;
  2144.     RotY[0]=cost*y+sint*x;
  2145.  
  2146.     x=RotX[1]; y=RotY[1];
  2147.     RotX[1]=cost*x-sint*y;
  2148.     RotY[1]=cost*y+sint*x;
  2149.  
  2150.     x=RotX[2]; y=RotY[2];
  2151.     RotX[2]=cost*x-sint*y;
  2152.     RotY[2]=cost*y+sint*x;
  2153.  
  2154.     if( CenX || CenY || CenZ )
  2155.     {   ncost = 1.0-cost;
  2156.         temp =  CenX*(ncost*RotX[0] - sint*RotY[0]);
  2157.         temp += CenY*(ncost*RotX[1] - sint*RotY[1]);
  2158.         temp += CenZ*(ncost*RotX[2] - sint*RotY[2]);
  2159.         temp = DialValue[4] - (Scale*temp)/XRange;
  2160.  
  2161.         if( temp < -1.0 )
  2162.         {   DialValue[4] = -1.0;
  2163.         } else if( temp > 1.0 )
  2164.         {   DialValue[4] = 1.0;
  2165.         } else DialValue[4] = temp;
  2166.  
  2167.         ncost = 1.0-cost;
  2168.         temp =  CenX*(ncost*RotY[0] + sint*RotX[0]);
  2169.         temp += CenY*(ncost*RotY[1] + sint*RotX[1]);
  2170.         temp += CenZ*(ncost*RotY[2] + sint*RotX[2]);
  2171.         temp = DialValue[5] - (Scale*temp)/YRange;
  2172.  
  2173.         if( temp < -1.0 )
  2174.         {   DialValue[5] = -1.0;
  2175.         } else if( temp > 1.0 )
  2176.         {   DialValue[5] = 1.0;
  2177.         } else DialValue[5] = temp;
  2178.     }
  2179.     }
  2180. }
  2181.  
  2182.  
  2183. void ApplyTransform()
  2184. {
  2185.     register int temp;
  2186.     register Real x, y, z;
  2187.     register int oldx,oldy;
  2188.     register Chain __far *chain;
  2189.     register Group __far *group;
  2190.     register HBond __far *hptr;
  2191.     register Bond __far *bptr;
  2192.     register Atom __far *ptr;
  2193.  
  2194.  
  2195.     if( ReDrawFlag & RFMagnify )
  2196.     {   if( DialValue[3] <= 0.0 )
  2197.     {   Zoom = DialValue[3]+1.0;
  2198.         if( Zoom<0.1 ) Zoom=0.1;
  2199.     } else Zoom = (DialValue[3]*MaxZoom) + 1.0;
  2200.  
  2201.     Scale = Zoom*DScale*Range;
  2202.     ImageSize = (int)(Scale*WorldSize);
  2203.     ImageRadius = ImageSize>>1;
  2204.     IScale = 1.0/Scale;
  2205.  
  2206.     MaxAtomRadius = 0;
  2207.     MaxBondRadius = 0;
  2208.     }
  2209.  
  2210.     if( ReDrawFlag & RFRotate )
  2211.     {   PrepareTransform();
  2212.     if( UseShadow )
  2213.         ShadowTransform();
  2214.     }
  2215.  
  2216.     if( ReDrawFlag & (RFRotate|RFMagnify) )
  2217.     {   MatX[0] = Scale*RotX[0]; 
  2218.     MatX[1] = Scale*RotX[1];
  2219.     MatX[2] = Scale*RotX[2];
  2220.  
  2221.     MatY[0] = Scale*RotY[0];
  2222.     MatY[1] = Scale*RotY[1];
  2223.     MatY[2] = Scale*RotY[2];
  2224.  
  2225.     MatZ[0] = Scale*RotZ[0];
  2226.     MatZ[1] = Scale*RotZ[1];
  2227.     MatZ[2] = Scale*RotZ[2];
  2228.  
  2229.     if( UseShadow )
  2230.     {   InvX[0] = IScale*RotX[0]; 
  2231.         InvX[1] = IScale*RotY[0];
  2232.         InvX[2] = IScale*RotZ[0];
  2233.  
  2234.         InvY[0] = IScale*RotX[1];
  2235.         InvY[1] = IScale*RotY[1];
  2236.         InvY[2] = IScale*RotZ[1];
  2237.  
  2238.         InvZ[0] = IScale*RotX[2];
  2239.         InvZ[1] = IScale*RotY[2];
  2240.         InvZ[2] = IScale*RotZ[2];
  2241.     }
  2242.     }
  2243.  
  2244.     oldx = XOffset;
  2245.     oldy = YOffset;
  2246.     XOffset = WRange + (int)(DialValue[4]*XRange);
  2247.     YOffset = HRange + (int)(DialValue[5]*YRange);
  2248.  
  2249.     /* Zoom dependent Translation! */
  2250.     /* XOffset = WRange + (int)(DialValue[4]*ImageSize); */
  2251.     /* YOffset = HRange + (int)(DialValue[5]*ImageSize); */
  2252.  
  2253.  
  2254.     switch( ReDrawFlag )
  2255.     {   case(RFTransX):
  2256.         if( XOffset != oldx ) 
  2257.                 {   temp = XOffset - oldx;
  2258.             ForEachAtom ptr->x += temp;
  2259.                 }
  2260.         break;
  2261.  
  2262.     case(RFTransY):
  2263.         if( YOffset != oldy ) 
  2264.                 {   temp = YOffset - oldy;
  2265.             ForEachAtom ptr->y += temp;
  2266.                 }
  2267.         break;
  2268.  
  2269.     case(RFRotateX):
  2270.         ForEachAtom
  2271.         {   x = ptr->xorg; y = ptr->yorg; z = ptr->zorg;
  2272.         ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset;
  2273.         ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset;
  2274.         }
  2275.         break;
  2276.  
  2277.     case(RFRotateY):
  2278.         ForEachAtom
  2279.         {   x = ptr->xorg; y = ptr->yorg; z = ptr->zorg;
  2280.         ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset;
  2281.         ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset;
  2282.         }
  2283.         break;
  2284.  
  2285.     case(RFRotateZ):
  2286.         ForEachAtom
  2287.         {   x = ptr->xorg; y = ptr->yorg; z = ptr->zorg;
  2288.         ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset;
  2289.         ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset;
  2290.         }
  2291.         break;
  2292.  
  2293.     default:
  2294.         if( DrawAtoms && (ReDrawFlag&RFMagnify) )
  2295.         {   ForEachAtom 
  2296.         {   x = ptr->xorg; y = ptr->yorg; z = ptr->zorg;
  2297.             ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset;
  2298.             ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset;
  2299.             ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset;
  2300.             if( ptr->flag&SphereFlag )
  2301.             {   ptr->irad = (int)(Scale*ptr->radius);
  2302.             if( ptr->irad>MaxAtomRadius )
  2303.                 MaxAtomRadius = ptr->irad;
  2304.             }
  2305.         }
  2306.         } else
  2307.         ForEachAtom 
  2308.         {   x = ptr->xorg; y = ptr->yorg; z = ptr->zorg;
  2309.             ptr->x = (int)(x*MatX[0]+y*MatX[1]+z*MatX[2])+XOffset;
  2310.             ptr->y = (int)(x*MatY[0]+y*MatY[1]+z*MatY[2])+YOffset;
  2311.             ptr->z = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2])+ZOffset;
  2312.         }
  2313.  
  2314.         if( ReDrawFlag & RFMagnify )
  2315.         {   if( DrawBonds )
  2316.             ForEachBond
  2317.             if( bptr->flag&CylinderFlag )
  2318.             {   bptr->irad = (int)(Scale*bptr->radius);
  2319.                 if( bptr->irad>MaxBondRadius )
  2320.                 MaxBondRadius = bptr->irad;
  2321.             }
  2322.  
  2323.         for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
  2324.             if( hptr->flag&CylinderFlag )
  2325.             hptr->irad = (int)(Scale*hptr->radius);
  2326.  
  2327.         for( hptr=Database->slist; hptr; hptr=hptr->hnext )
  2328.             if( hptr->flag&CylinderFlag )
  2329.             hptr->irad = (int)(Scale*hptr->radius);
  2330.  
  2331.         ForEachBack
  2332.             if( bptr->flag&CylinderFlag )
  2333.             bptr->irad = (int)(Scale*bptr->radius);
  2334.         }
  2335.     }
  2336.  
  2337.     DetermineClipping();
  2338.     if( UseScreenClip || ReDrawFlag!=RFRotateY )
  2339.     BucketFlag = False;
  2340. }
  2341.  
  2342.  
  2343. void ResetTransform()
  2344. {
  2345.     RotX[0] = 1.0;  RotX[1] = 0.0;  RotX[2] = 0.0;
  2346.     RotY[0] = 0.0;  RotY[1] = 1.0;  RotY[2] = 0.0;
  2347.     RotZ[0] = 0.0;  RotZ[1] = 0.0;  RotZ[2] = 1.0;
  2348.     LastRX = LastRY = LastRZ = 0.0;
  2349.     CenX = CenY = CenZ = 0;
  2350. }
  2351.  
  2352.  
  2353. void InitialiseTransform()
  2354. {
  2355.     ColourDepth = DefaultColDepth;
  2356.     ColourMask = ColourDepth-1;
  2357.  
  2358. #ifdef APPLEMAC
  2359.     LastShade = Colour2Shade(LutSize-1);
  2360. #else
  2361.     LastShade = Colour2Shade(LutSize);
  2362. #endif
  2363.  
  2364.     ResetColourMap();
  2365.     ResetTransform();
  2366.  
  2367.     ZoneBoth = True;
  2368.     HetaGroups = True;
  2369.     Hydrogens = True;
  2370. }
  2371.  
  2372.